﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

namespace DNA.OpenAPI.Rss
{
    public class RssChannelBuilder
    {
        private RssChannel channel;

        public RssChannelBuilder(string title, string desc = "", string link = "", string language = "")
        {
            channel = new RssChannel()
            {
                Title = title,
                Items=new List<RssItem>()
            };

            if (!string.IsNullOrEmpty(desc)) channel.Description = desc;
            if (!string.IsNullOrEmpty(link)) channel.Link = link;
            if (!string.IsNullOrEmpty(language)) channel.Language = language;
        }

        /// <summary>
        /// Set A URL that points to the documentation for the format used in the RSS file. 
        /// </summary>
        /// <param name="url"></param>
        public void SetDocUrl(string url)
        {
            channel.DocUrl = url;
        }

        /// <summary>
        /// Specifies a GIF, JPEG or PNG image that can be displayed with the channel
        /// </summary>
        /// <param name="src"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="href"></param>
        /// <param name="title"></param>
        public void SetImage(string src, int? width, int? height, string href = "", string title = "")
        {
            channel.Image = new RssImage()
            {
                ImageUrl = src
            };
            if (width.HasValue) channel.Image.Width = width.Value;
            if (height.HasValue) channel.Image.Height = height.Value;
            if (!string.IsNullOrEmpty(href))
                channel.Image.NavigateUrl = href;
            if (!string.IsNullOrEmpty(title))
                channel.Image.Description = title;
        }

        /// <summary>
        /// A channel may optionally contain a <textInput> sub-element, which contains four required sub-elements.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="title"></param>
        /// <param name="desc"></param>
        /// <param name="link"></param>
        public void SetTextInput(string name, string title, string desc = "", string link = "")
        {
            channel.TextInput = new RssTextInput()
            {
                Name = name,
                Title = title
            };
            if (!string.IsNullOrEmpty(desc))
                channel.TextInput.Description = desc;
            if (!string.IsNullOrEmpty(link))
                channel.TextInput.Link = link;
        }
        
        public void SetTTL(int minute)
        {
            channel.TTL = minute;
        }

        public void SetClound(string domain, string path, string registerProcedure, int? port = 80, string protocol = "xml-rpc")
        {
            channel.Cloud = new RssCloud()
            {
                Domain = domain,
                Path = path,
                Port = port.Value,
                Protocol = protocol
            };
        }

        public void SetLastBuild(DateTime date)
        {
            channel.LastBuildDate = date.ToString("r");
        }

        public void SetPublished(DateTime date)
        {
            channel.PubDate = date.ToString("r");
        }

        public void AddItems<T>(IEnumerable<T> model,Action<T,RssItemBuilder> director)
        {
            foreach (var m in model)
            {
                var b = new RssItemBuilder();
                director(m, b);
                AddItem(b.Item);
            }
        }

        public void AddItems(IEnumerable<RssItem> items)
        {
            channel.Items.AddRange(items);
        }

        public void AddItem(RssItem item)
        {
            channel.Items.Add(item);
        }

        ///// <summary>
        ///// An XML element that contains up to 24 hour sub-elements whose value is a number between 0 and 23, representing a time in GMT, when aggregators, if they support the feature, may not read the channel on hours listed in the skipHours element.
        ///// </summary>
        ///// <param name="hours"></param>
        //public void SkipHours(int hours)
        //{
        //    if ((hours >= 0) && (hours <= 24))
        //    {
        //        channel.SkipHours = hours.ToString();
        //    }
        //}

        public void AddCategories(string[] categories)
        {
            if (channel.Categories == null)
                channel.Categories = new List<string>();
            channel.Categories.AddRange(categories);
        }

        public void AddCategory(string category)
        {
            if (channel.Categories == null)
                channel.Categories = new List<string>();
            channel.Categories.Add(category);
        }

        public string GetXml()
        {
            var ser = new XmlSerializer(typeof(RssChannel));
            var xml = "<?xml version=\"1.0\">";
            using (var stream = new MemoryStream())
            {
                using (var writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8))
                {
                    writer.Formatting = Formatting.None;
                    ser.Serialize(writer, channel);
                    writer.Flush();
                    stream.Position = 0;
                    var reader = new StreamReader(stream, System.Text.Encoding.UTF8);
                    xml = reader.ReadToEnd();
                    reader.Close();
                }
            }
            return xml;
        }

        public RssChannel GetChannel()
        {
            return channel;
        }
    }
}
